package xyz.ddlnt.servicemg.service.impl;

import com.alibaba.cloud.commons.lang.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import xyz.ddlnt.commonutil.constant.FieldConstants;
import xyz.ddlnt.commonutil.enumeration.ResultCode;
import xyz.ddlnt.commonutil.exception.GlobalException;
import xyz.ddlnt.commonutil.util.RandomUtil;
import xyz.ddlnt.model.dto.TechnologyDTO;
import xyz.ddlnt.model.entity.Technology;
import xyz.ddlnt.model.vo.TechnologyInfoVO;
import xyz.ddlnt.model.vo.TechnologySelectVO;
import xyz.ddlnt.model.vo.TechnologyVO;
import xyz.ddlnt.servicemg.mapper.CategoryMapper;
import xyz.ddlnt.servicemg.mapper.TechnologyMapper;
import xyz.ddlnt.servicemg.service.TechnologyService;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author ZZULI_SE 210910
 * @data 2025/5/1 20:55
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class TechnologyServiceImpl extends ServiceImpl<TechnologyMapper, Technology> implements TechnologyService {

    private final TechnologyMapper technologyMapper;
    private final CategoryMapper categoryMapper;
//    @Override
//    public List<TechnologyVO> selectAll() {
//        return technologyMapper.selectAll();
//    }
@Override
public List<TechnologyVO> selectAll() {
    List<TechnologyVO> technologyVOS = technologyMapper.selectAll();
    log.info("TechnologyVOS size: " + technologyVOS.size());
    for (TechnologyVO technologyVO : technologyVOS) {
        log.info(String.valueOf(technologyVO));
    }
    return technologyVOS;
}

    @Override
    public TechnologyVO addTechnology(TechnologyDTO technologyDTO) {
        if (technologyDTO.getCategoryId() == null) {
            throw new GlobalException(ResultCode.CATEGORY_NOT_SELECTED);
        }
        if (StringUtils.isEmpty(technologyDTO.getTechnologyName())) {
            throw new GlobalException(ResultCode.NAME_NOT_ENTERED);
        }
        Long technologyId = RandomUtil.generate12DigitRandomNumber();
        LocalDateTime now = LocalDateTime.now();
        Technology technology = Technology.builder()
                .id(technologyId)
                .categoryId(technologyDTO.getCategoryId())
                .technologyName(technologyDTO.getTechnologyName())
                .technologyIcon(technologyDTO.getTechnologyIcon())
                .technologyIntroduce(technologyDTO.getTechnologyIntroduce())
                .createTime(now)
                .updateTime(now)
                .build();
        try { // 插入数据
            technologyMapper.insert(technology);
        }catch (Exception e){
            throw new GlobalException(ResultCode.NAME_ALREADY_EXISTS);
        }
        String categoryName = categoryMapper.selectCategoryNameById(technologyDTO.getCategoryId());
        return TechnologyVO.builder()
                .id(technologyId)
                .categoryName(categoryName)
                .technology(technology)
                .build();
    }

    @Override
    public LocalDateTime updateTechnology(TechnologyDTO technologyDTO) {
        LocalDateTime now = LocalDateTime.now();
        LambdaUpdateWrapper<Technology> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper
                .set(technologyDTO.getTechnologyName()!=null, Technology::getTechnologyName, technologyDTO.getTechnologyName())
                .set(technologyDTO.getTechnologyIcon()!=null, Technology::getTechnologyIcon, technologyDTO.getTechnologyIcon())
                .set(technologyDTO.getTechnologyIntroduce()!=null, Technology::getTechnologyIntroduce, technologyDTO.getTechnologyIntroduce())
                .set(Technology::getUpdateTime, now)
                .eq(Technology::getId, technologyDTO.getId());

        try { // 更新数据
            technologyMapper.update(updateWrapper);
        }catch (Exception e){
            throw new GlobalException(ResultCode.WITH_NEW_FAILURES);
        }
        return now;
    }

    @Override
    @Transactional // TODO Seata 分布式事务
    public Boolean deleteTechnology(Long technologyId) {
        // 删除科目信息
        int i = technologyMapper.deleteById(technologyId);
        // 删除科目信息下的试题信息

        // 删除科目信息下所有试题的浏览记录

        // 删除科目信息下所有试题的收藏记录

        // 删除科目信息下所有试题的点赞记录

        // 删除科目信息下所有试题的浏览记录
        return true;
    }

    @Override
    public List<TechnologySelectVO> selectTechCategoryInfos() {
        return technologyMapper.selectTreeSelectInfo();
    }

    @Override
    public List<TechnologyInfoVO> selectByCategoryId(Long categoryId) {
        LambdaQueryWrapper<Technology> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(!Objects.equals(categoryId, FieldConstants.ALL_CATEGORIES), Technology::getCategoryId, categoryId)
                .select(Technology::getId, Technology::getTechnologyName, Technology::getTechnologyIcon, Technology::getTechnologyIntroduce);
        List<Technology> technologies = technologyMapper.selectList(queryWrapper);
        // 封装成 TechnologyInfoVOS
        return technologies.stream().map(technology -> {
            TechnologyInfoVO technologyInfoVO = new TechnologyInfoVO();
            BeanUtils.copyProperties(technology, technologyInfoVO);
            return technologyInfoVO;
        }).toList();
    }

    @Override
    public TechnologyInfoVO selectByTechnologyId(Long technologyId) {
        LambdaQueryWrapper<Technology> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Technology::getId, technologyId)
                .select(Technology::getId, Technology::getTechnologyName, Technology::getTechnologyIcon, Technology::getTechnologyIntroduce);
        Technology technology = technologyMapper.selectOne(queryWrapper);
        TechnologyInfoVO technologyInfoVO = new TechnologyInfoVO();
        BeanUtils.copyProperties(technology, technologyInfoVO);
        return technologyInfoVO;
    }
}
